package facade;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import easyaccept.EasyAcceptFacade;
import excecoes.ContaException;
import excecoes.IPException;
import excecoes.LocalizacaoException;
import excecoes.MensagemException;
import excecoes.PessoaException;
import excecoes.SistemaException;
import excecoes.UsuarioException;
import sistema.Sistema;

/**
 * Classe que implementa a fachada principal do sistema.
 * 
 * @author Adalberto Teixeira
 * @author Andrey Nogueira
 * @author Laise Florentino
 * @author Laio Francis
 * 
 */
public class Facade {

	private static Facade instance;

	private Sistema novoSistema;

	/**
	 * Inicia o sistema.
	 * Construtor da classe Facade.
	 */
	public Facade() {
		novoSistema = new Sistema();
		//instance = Facade.getInstance(); DAH ERRO!!
	}

	/**
	 * Cria uma instancia da fachada
	 * Padrao Facade
	 * 
	 * @return instance Nova instancia
	 */
	public static Facade getInstance() {
		if (instance == null) {
			instance = new Facade();
		}
		return instance;
	}

	/**
	 * Cria Novo Usuario.
	 * 
	 * @param userName
	 * @param nome
	 * @param email
	 * @param senha
	 * @param telefone
	 * 
	 * @throws ContaException
	 * @throws UsuarioException 
	 * @throws PessoaException 
	 */
	public void criarUsuario(String userName, String nome, String email,
			String senha, String telefone) throws ContaException, UsuarioException, PessoaException {
		novoSistema.criarUsuario(userName, nome, email, senha, telefone);

	}

	/**
	 * Retorna o usuario a partir do nome.
	 * 
	 * @param nome
	 * @param indice
	 * @return String com o usuario
	 * 
	 * @throws ContaException
	 */
	public String getUsuarioPorNome(String nome, String indice)
			throws ContaException {
		return novoSistema.getUsuarioPorNome(nome, indice);
	}

	/**
	 * Retorna o atributo pedido a partir do ID.
	 * 
	 * @param id
	 * @param atributo
	 * @return String com o atributo
	 * 
	 * @throws ContaException
	 */
	public String getAtributoUsuario(String id, String atributo)
			throws ContaException {
		return novoSistema.getAtributoUsuario(id, atributo);
	}

	/**
	 * Atualiza os dados do usuario.
	 * 
	 * @param id
	 * @param atributo
	 * @param valor
	 * 
	 * @throws ContaException
	 * @throws IPException
	 * @throws UsuarioException 
	 * @throws PessoaException 
	 */
	public void atualizarUsuario(String id, String atributo, String valor)
			throws ContaException, IPException, PessoaException, UsuarioException {
		novoSistema.atualizarUsuario(id, atributo, valor);
	}

	/**
	 * Zera o sistema
	 */
	public void zerarSistema() {
		novoSistema.zerarSistema();
	}

	/**
	 * Remove o usuario a partir do ID.
	 * 
	 * @param id
	 * 
	 * @throws ContaException
	 */
	public void removerUsuario(String id) throws ContaException {
		novoSistema.removerUsuario(id);
	}

	/**
	 * Cadastra usuario.
	 * 
	 * @param userName
	 * @param nome
	 * @param email
	 * @param senha
	 * @param telefone
	 * @param ip
	 * @return String
	 * 
	 * @throws ContaException
	 * @throws SistemaException
	 * @throws IPException
	 * @throws UsuarioException 
	 * @throws PessoaException 
	 */
	public String cadastrarUsuario(String userName, String nome, String email,
			String senha, String telefone, String ip) throws ContaException,
			SistemaException, IPException, UsuarioException, PessoaException {
		return novoSistema.cadastrarUsuario(userName, nome, email, senha, telefone,
				ip);

	}

	/**
	 * Faz login.
	 * 
	 * @param userName
	 * @param senha
	 * @param ip
	 * @return String
	 * 
	 * @throws SistemaException
	 * @throws ContaException
	 * @throws IPException
	 */
	public String login(String userName, String senha, String ip)
			throws SistemaException, ContaException, IPException {
		return novoSistema.login(userName, senha, ip);
	}

	/**
	 * Retorna se o usuario esta conectado.
	 * 
	 * @param usuario
	 * @return true se o usuario estiver conectado, false caso contrario
	 */
	public boolean estaConectado(String usuario) {
		return novoSistema.estaConectado(usuario);
	}

	/**
	 * Faz logout do usuario.
	 * 
	 * @param id
	 * 
	 * @throws SistemaException
	 */
	public void logout(String id) throws SistemaException {
		novoSistema.logout(id);
	}

	/**
	 * Retorna os localizadores.
	 * 
	 * @return String com localizadores
	 */
	public String getLocalizadores(){
		return novoSistema.getLocalizadores();
	}
	
	/**
	 * Retorna a localizacao.
	 * 
	 * @param usuario
	 * @return String com localizacao do usuario
	 * 
	 * @throws IPException
	 * @throws IOException
	 * @throws ContaException
	 */
	public String obterLocalizacao(String usuario) throws IPException, IOException, ContaException{
		return novoSistema.obterLocalizacao(usuario);
	}
	
	/**
	 * Seta a localizacao manualmente.
	 * 
	 * @param usuario
	 * @param latitude
	 * @param longitude
	 * 
	 * @throws ContaException
	 * @throws SistemaException
	 * @throws LocalizacaoException 
	 */
	public void setLocalizacao(String usuario, String latitude, String longitude) throws ContaException, SistemaException, LocalizacaoException{
		novoSistema.setLocalizacao(usuario, latitude, longitude);
	}
	
	/**
	 * Retorna a localizacao do usuario.
	 * 
	 * @param usuario
	 * @return String com localizacao
	 * 
	 * @throws SistemaException
	 */
	public String getLocalizacao(String usuario) throws SistemaException{
		return novoSistema.getLocalizacao(usuario);
	}
	
	/**
	 * Incializa um novo mensageiro.
	 * 
	 * @param sistema
	 * 
	 * @throws SistemaException
	 */
	public void initMensageiro(String sistema) throws SistemaException{
		novoSistema.initMensageiro(sistema);
	}
	
	/**
	 * Seta o diretorio dos logs.
	 * 
	 * @param valor
	 */
	public void setDiretorioGabaritos(String valor){
		novoSistema.setDiretorioGabaritos(valor);
	}
	
	/**
	 * Envia novo convite.
	 * 
	 * @param de
	 * @param para
	 * @return String com confirmacao de envio
	 * 
	 * @throws IOException
	 */
	public String enviarConvite(String de, String para) throws IOException{
		return novoSistema.enviarConvite(de, para);
	}
	
	/**
	 * Confirma compartilhamento.
	 * 
	 * @param de
	 * @param com
	 * @param modo
	 * 
	 * @throws ContaException
	 */
	public void confirmarCompartilhamento(String de, String com, int modo) throws ContaException{
		novoSistema.confirmarCompartilhamento(de, com, modo, true);
	}
	
	/**
	 * Remover compartilhamento com algum usuario.
	 * 
	 * @param de
	 * @param com
	 * 
	 * @throws ContaException
	 */
	public void recusarCompartilhamento(String de, String com) throws ContaException{
		novoSistema.recusarCompartilhamento(de, com);
	}
	
	/**
	 * Retorna os amigos do usuario.
	 * 
	 * @param usuario
	 * @return String com lista de amigos
	 * 
	 * @throws ContaException
	 */
	public String getAmigos(String usuario) throws ContaException{
		return novoSistema.getAmigos(usuario);
	}
	
	/**
	 * Retorna localizacao do amigo.
	 * 
	 * @param id
	 * @param amigo
	 * @return String com localizacao
	 * 
	 * @throws ContaException
	 * @throws SistemaException
	 */
	public String getLocalizacaoAmigo(String id, String amigo) throws ContaException, SistemaException{
		return novoSistema.getLocalizacaoAmigo(id, amigo);
	}
	
	/**
	 * Retorna a possivel localizacao.
	 * 
	 * @param usuario
	 * @param amigo
	 * @return true se posso ver localizacao, false se nao
	 * 
	 * @throws ContaException
	 * @throws SistemaException
	 */
	public boolean possoVerLocalizacao(String usuario, String amigo) throws ContaException, SistemaException{
		return novoSistema.possoVerLocalizacao(usuario,amigo);
	}
	
	/**
	 * Seta o tipo de compartilhamento com o amigo.
	 * 
	 * @param usuario
	 * @param amigo
	 * @param modo
	 * 
	 * @throws ContaException
	 */
	public void setCompartilhamento(String usuario, String amigo, int modo) throws ContaException{
		novoSistema.confirmarCompartilhamento(usuario, amigo, modo, false);
	}
	
	/**
	 * Envia  email.
	 * 
	 * @param de
	 * @param para
	 * @param assunto
	 * @param msg
	 * @return String com confirmacao de envio
	 * 
	 * @throws MensagemException
	 * @throws IOException
	 */
	public String enviarEmail(String de, String para, String assunto, String msg) throws MensagemException, IOException{
		return novoSistema.enviarEmail(de, para, assunto, msg);
	}
	
	/**
	 * Envvia SMS.
	 * 
	 * @param de
	 * @param para
	 * @param msg
	 * @return String com confirmacao de envio
	 * 
	 * @throws MensagemException
	 * @throws IOException
	 */
	public String enviarSMS(String de, String para, String msg) throws MensagemException, IOException{
		return novoSistema.enviarSMS(de, para, msg);
	}
	
	/**
	 * Seta a porta do Chat.
	 * 
	 * @param port
	 * 
	 * @throws SistemaException
	 */
	public void setPortChat(int port) throws SistemaException{
		novoSistema.setPortChat(port);
	}
	
	/**
	 * Incializa mensageiro instantaneo.
	 * 
	 * @param de
	 * @param para
	 * 
	 * @throws SistemaException
	 */
	public void initChat(String de, String para) throws SistemaException{
		novoSistema.initChat(de, para);
	}
	
	/**
	 * Encerra mensageiro instantaneo.
	 * 
	 * @param de
	 * @param com
	 * 
	 * @throws IOException
	 */
	public void encerrarChat(String de, String com) throws IOException{
		novoSistema.encerrarChat(de, com);
	}
	
	/**
	 * Envia mensagem.
	 * 
	 * @param para
	 * @param msg
	 */
	public void enviarMensagem(String para, String msg) {
		novoSistema.enviarMensagem(para,msg);
	}
	
	/**
	 * Recebe as mensagens do usuario.
	 * 
	 * @param de
	 * @return String com mensagem
	 */
	public String receberMensagem(String de){
		return novoSistema.receberMensagem(de);
		
	}
	
	/**
	 * Encerra o sistema.
	 * 
	 * @throws IOException
	 */
	public void encerrarSistema() throws IOException {
		novoSistema.encerrarSistema();
	}
	
	/**
	 * Remove o amigo.
	 * 
	 * @param usuario
	 * @param amigo
	 * 
	 * @throws ContaException
	 */
	public void removerAmigo(String usuario, String amigo) throws ContaException{
		novoSistema.removerAmigo(usuario, amigo);
	}

	public static void main(String[] args) throws Exception {

		List<String> arquivos = new ArrayList<String>();

		arquivos.add("ImHereM03/testes_aceitacao/us1.txt");
		arquivos.add("ImHereM03/testes_aceitacao/us2.txt");
		arquivos.add("ImHereM03/testes_aceitacao/us3.txt");
		arquivos.add("ImHereM03/testes_aceitacao/us4.txt");
		arquivos.add("ImHereM03/testes_aceitacao/us5.txt");
		arquivos.add("ImHereM03/testes_aceitacao/us6.txt");
		arquivos.add("ImHereM03/testes_aceitacao/us7_1.txt");
		arquivos.add("ImHereM03/testes_aceitacao/us7_2.txt");
		arquivos.add("ImHereM03/testes_aceitacao/us7_3.txt");

		Facade sistemaFachada = new Facade();

		EasyAcceptFacade eaFacade = new EasyAcceptFacade(sistemaFachada,
				arquivos);
		eaFacade.executeTests();

		System.out.println(eaFacade.getCompleteResults());

	}

}
